home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / include / math-emu / op-common.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  25.8 KB  |  872 lines

  1. /* Software floating-point emulation. Common operations.
  2.    Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
  3.    This file is part of the GNU C Library.
  4.    Contributed by Richard Henderson (rth@cygnus.com),
  5.           Jakub Jelinek (jj@ultra.linux.cz),
  6.           David S. Miller (davem@redhat.com) and
  7.           Peter Maydell (pmaydell@chiark.greenend.org.uk).
  8.  
  9.    The GNU C Library is free software; you can redistribute it and/or
  10.    modify it under the terms of the GNU Library General Public License as
  11.    published by the Free Software Foundation; either version 2 of the
  12.    License, or (at your option) any later version.
  13.  
  14.    The GNU C Library is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.    Library General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU Library General Public
  20.    License along with the GNU C Library; see the file COPYING.LIB.  If
  21.    not, write to the Free Software Foundation, Inc.,
  22.    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  23.  
  24. #ifndef __MATH_EMU_OP_COMMON_H__
  25. #define __MATH_EMU_OP_COMMON_H__
  26.  
  27. #define _FP_DECL(wc, X)            \
  28.   _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0;    \
  29.   _FP_FRAC_DECL_##wc(X)
  30.  
  31. /*
  32.  * Finish truely unpacking a native fp value by classifying the kind
  33.  * of fp value and normalizing both the exponent and the fraction.
  34.  */
  35.  
  36. #define _FP_UNPACK_CANONICAL(fs, wc, X)                    \
  37. do {                                    \
  38.   switch (X##_e)                            \
  39.   {                                    \
  40.   default:                                \
  41.     _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;            \
  42.     _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);                    \
  43.     X##_e -= _FP_EXPBIAS_##fs;                        \
  44.     X##_c = FP_CLS_NORMAL;                        \
  45.     break;                                \
  46.                                     \
  47.   case 0:                                \
  48.     if (_FP_FRAC_ZEROP_##wc(X))                        \
  49.       X##_c = FP_CLS_ZERO;                        \
  50.     else                                \
  51.       {                                    \
  52.     /* a denormalized number */                    \
  53.     _FP_I_TYPE _shift;                        \
  54.     _FP_FRAC_CLZ_##wc(_shift, X);                    \
  55.     _shift -= _FP_FRACXBITS_##fs;                    \
  56.     _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));            \
  57.     X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;                \
  58.     X##_c = FP_CLS_NORMAL;                        \
  59.     FP_SET_EXCEPTION(FP_EX_DENORM);                    \
  60.     if (FP_DENORM_ZERO)                        \
  61.       {                                \
  62.         FP_SET_EXCEPTION(FP_EX_INEXACT);                \
  63.         X##_c = FP_CLS_ZERO;                    \
  64.       }                                \
  65.       }                                    \
  66.     break;                                \
  67.                                     \
  68.   case _FP_EXPMAX_##fs:                            \
  69.     if (_FP_FRAC_ZEROP_##wc(X))                        \
  70.       X##_c = FP_CLS_INF;                        \
  71.     else                                \
  72.       {                                    \
  73.     X##_c = FP_CLS_NAN;                        \
  74.     /* Check for signaling NaN */                    \
  75.     if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))        \
  76.       FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN);        \
  77.       }                                    \
  78.     break;                                \
  79.   }                                    \
  80. } while (0)
  81.  
  82. /*
  83.  * Before packing the bits back into the native fp result, take care
  84.  * of such mundane things as rounding and overflow.  Also, for some
  85.  * kinds of fp values, the original parts may not have been fully
  86.  * extracted -- but that is ok, we can regenerate them now.
  87.  */
  88.  
  89. #define _FP_PACK_CANONICAL(fs, wc, X)                \
  90. do {                                \
  91.   switch (X##_c)                        \
  92.   {                                \
  93.   case FP_CLS_NORMAL:                        \
  94.     X##_e += _FP_EXPBIAS_##fs;                    \
  95.     if (X##_e > 0)                        \
  96.       {                                \
  97.     _FP_ROUND(wc, X);                    \
  98.     if (_FP_FRAC_OVERP_##wc(fs, X))                \
  99.       {                            \
  100.         _FP_FRAC_CLEAR_OVERP_##wc(fs, X);            \
  101.         X##_e++;                        \
  102.       }                            \
  103.     _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);            \
  104.     if (X##_e >= _FP_EXPMAX_##fs)                \
  105.       {                            \
  106.         /* overflow */                    \
  107.         switch (FP_ROUNDMODE)                \
  108.           {                            \
  109.           case FP_RND_NEAREST:                \
  110.         X##_c = FP_CLS_INF;                \
  111.         break;                        \
  112.           case FP_RND_PINF:                    \
  113.         if (!X##_s) X##_c = FP_CLS_INF;            \
  114.         break;                        \
  115.           case FP_RND_MINF:                    \
  116.         if (X##_s) X##_c = FP_CLS_INF;            \
  117.         break;                        \
  118.           }                            \
  119.         if (X##_c == FP_CLS_INF)                \
  120.           {                            \
  121.         /* Overflow to infinity */            \
  122.         X##_e = _FP_EXPMAX_##fs;            \
  123.         _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
  124.           }                            \
  125.         else                        \
  126.           {                            \
  127.         /* Overflow to maximum normal */        \
  128.         X##_e = _FP_EXPMAX_##fs - 1;            \
  129.         _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);        \
  130.           }                            \
  131.         FP_SET_EXCEPTION(FP_EX_OVERFLOW);            \
  132.             FP_SET_EXCEPTION(FP_EX_INEXACT);            \
  133.       }                            \
  134.       }                                \
  135.     else                            \
  136.       {                                \
  137.     /* we've got a denormalized number */            \
  138.     X##_e = -X##_e + 1;                    \
  139.     if (X##_e <= _FP_WFRACBITS_##fs)            \
  140.       {                            \
  141.         _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
  142.         if (_FP_FRAC_HIGH_##fs(X)                \
  143.         & (_FP_OVERFLOW_##fs >> 1))            \
  144.           {                            \
  145.             X##_e = 1;                    \
  146.             _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
  147.           }                            \
  148.         else                        \
  149.           {                            \
  150.         _FP_ROUND(wc, X);                \
  151.         if (_FP_FRAC_HIGH_##fs(X)            \
  152.            & (_FP_OVERFLOW_##fs >> 1))            \
  153.           {                        \
  154.             X##_e = 1;                    \
  155.             _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);    \
  156.             FP_SET_EXCEPTION(FP_EX_INEXACT);        \
  157.           }                        \
  158.         else                        \
  159.           {                        \
  160.             X##_e = 0;                    \
  161.             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);        \
  162.           }                        \
  163.           }                            \
  164.         if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) ||        \
  165.         (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))    \
  166.         FP_SET_EXCEPTION(FP_EX_UNDERFLOW);        \
  167.       }                            \
  168.     else                            \
  169.       {                            \
  170.         /* underflow to zero */                \
  171.         X##_e = 0;                        \
  172.         if (!_FP_FRAC_ZEROP_##wc(X))            \
  173.           {                            \
  174.             _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);        \
  175.             _FP_ROUND(wc, X);                \
  176.             _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);    \
  177.           }                            \
  178.         FP_SET_EXCEPTION(FP_EX_UNDERFLOW);            \
  179.       }                            \
  180.       }                                \
  181.     break;                            \
  182.                                 \
  183.   case FP_CLS_ZERO:                        \
  184.     X##_e = 0;                            \
  185.     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
  186.     break;                            \
  187.                                 \
  188.   case FP_CLS_INF:                        \
  189.     X##_e = _FP_EXPMAX_##fs;                    \
  190.     _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
  191.     break;                            \
  192.                                 \
  193.   case FP_CLS_NAN:                        \
  194.     X##_e = _FP_EXPMAX_##fs;                    \
  195.     if (!_FP_KEEPNANFRACP)                    \
  196.       {                                \
  197.     _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);            \
  198.     X##_s = _FP_NANSIGN_##fs;                \
  199.       }                                \
  200.     else                            \
  201.       _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;        \
  202.     break;                            \
  203.   }                                \
  204. } while (0)
  205.  
  206. /* This one accepts raw argument and not cooked,  returns
  207.  * 1 if X is a signaling NaN.
  208.  */
  209. #define _FP_ISSIGNAN(fs, wc, X)                    \
  210. ({                                \
  211.   int __ret = 0;                        \
  212.   if (X##_e == _FP_EXPMAX_##fs)                    \
  213.     {                                \
  214.       if (!_FP_FRAC_ZEROP_##wc(X)                \
  215.       && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))    \
  216.     __ret = 1;                        \
  217.     }                                \
  218.   __ret;                            \
  219. })
  220.  
  221.  
  222.  
  223.  
  224.  
  225. /*
  226.  * Main addition routine.  The input values should be cooked.
  227.  */
  228.  
  229. #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                     \
  230. do {                                         \
  231.   switch (_FP_CLS_COMBINE(X##_c, Y##_c))                     \
  232.   {                                         \
  233.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                 \
  234.     {                                         \
  235.       /* shift the smaller number so that its exponent matches the larger */ \
  236.       _FP_I_TYPE diff = X##_e - Y##_e;                         \
  237.                                          \
  238.       if (diff < 0)                                 \
  239.     {                                     \
  240.       diff = -diff;                                 \
  241.       if (diff <= _FP_WFRACBITS_##fs)                     \
  242.         _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);             \
  243.       else if (!_FP_FRAC_ZEROP_##wc(X))                     \
  244.         _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                 \
  245.       R##_e = Y##_e;                             \
  246.     }                                     \
  247.       else                                     \
  248.     {                                     \
  249.       if (diff > 0)                                 \
  250.         {                                     \
  251.           if (diff <= _FP_WFRACBITS_##fs)                     \
  252.             _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);             \
  253.           else if (!_FP_FRAC_ZEROP_##wc(Y))                     \
  254.             _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                 \
  255.         }                                     \
  256.       R##_e = X##_e;                             \
  257.     }                                     \
  258.                                          \
  259.       R##_c = FP_CLS_NORMAL;                             \
  260.                                          \
  261.       if (X##_s == Y##_s)                             \
  262.     {                                     \
  263.       R##_s = X##_s;                             \
  264.       _FP_FRAC_ADD_##wc(R, X, Y);                         \
  265.       if (_FP_FRAC_OVERP_##wc(fs, R))                     \
  266.         {                                     \
  267.           _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);             \
  268.           R##_e++;                                 \
  269.         }                                     \
  270.     }                                     \
  271.       else                                     \
  272.     {                                     \
  273.       R##_s = X##_s;                             \
  274.       _FP_FRAC_SUB_##wc(R, X, Y);                         \
  275.       if (_FP_FRAC_ZEROP_##wc(R))                         \
  276.         {                                     \
  277.           /* return an exact zero */                     \
  278.           if (FP_ROUNDMODE == FP_RND_MINF)                     \
  279.         R##_s |= Y##_s;                             \
  280.           else                                 \
  281.         R##_s &= Y##_s;                             \
  282.           R##_c = FP_CLS_ZERO;                         \
  283.         }                                     \
  284.       else                                     \
  285.         {                                     \
  286.           if (_FP_FRAC_NEGP_##wc(R))                     \
  287.         {                                 \
  288.           _FP_FRAC_SUB_##wc(R, Y, X);                     \
  289.           R##_s = Y##_s;                         \
  290.         }                                 \
  291.                                          \
  292.           /* renormalize after subtraction */                 \
  293.           _FP_FRAC_CLZ_##wc(diff, R);                     \
  294.           diff -= _FP_WFRACXBITS_##fs;                     \
  295.           if (diff)                                 \
  296.         {                                 \
  297.           R##_e -= diff;                         \
  298.           _FP_FRAC_SLL_##wc(R, diff);                     \
  299.         }                                 \
  300.         }                                     \
  301.     }                                     \
  302.       break;                                     \
  303.     }                                         \
  304.                                          \
  305.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                     \
  306.     _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                         \
  307.     break;                                     \
  308.                                          \
  309.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):                 \
  310.     R##_e = X##_e;                                 \
  311.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                 \
  312.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                     \
  313.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                     \
  314.     _FP_FRAC_COPY_##wc(R, X);                             \
  315.     R##_s = X##_s;                                 \
  316.     R##_c = X##_c;                                 \
  317.     break;                                     \
  318.                                          \
  319.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):                 \
  320.     R##_e = Y##_e;                                 \
  321.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                 \
  322.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                     \
  323.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                     \
  324.     _FP_FRAC_COPY_##wc(R, Y);                             \
  325.     R##_s = Y##_s;                                 \
  326.     R##_c = Y##_c;                                 \
  327.     break;                                     \
  328.                                          \
  329.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                     \
  330.     if (X##_s != Y##_s)                                 \
  331.       {                                         \
  332.     /* +INF + -INF => NAN */                         \
  333.     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
  334.     R##_s = _FP_NANSIGN_##fs;                         \
  335.     R##_c = FP_CLS_NAN;                             \
  336.     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI);             \
  337.     break;                                     \
  338.       }                                         \
  339.     /* FALLTHRU */                                 \
  340.                                          \
  341.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):                 \
  342.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                     \
  343.     R##_s = X##_s;                                 \
  344.     R##_c = FP_CLS_INF;                                 \
  345.     break;                                     \
  346.                                          \
  347.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):                 \
  348.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                     \
  349.     R##_s = Y##_s;                                 \
  350.     R##_c = FP_CLS_INF;                                 \
  351.     break;                                     \
  352.                                          \
  353.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):                 \
  354.     /* make sure the sign is correct */                         \
  355.     if (FP_ROUNDMODE == FP_RND_MINF)                         \
  356.       R##_s = X##_s | Y##_s;                             \
  357.     else                                     \
  358.       R##_s = X##_s & Y##_s;                             \
  359.     R##_c = FP_CLS_ZERO;                             \
  360.     break;                                     \
  361.                                          \
  362.   default:                                     \
  363.     abort();                                     \
  364.   }                                         \
  365. } while (0)
  366.  
  367. #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
  368. #define _FP_SUB(fs, wc, R, X, Y)                         \
  369.   do {                                         \
  370.     if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;                     \
  371.     _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');                     \
  372.   } while (0)
  373.  
  374.  
  375. /*
  376.  * Main negation routine.  FIXME -- when we care about setting exception
  377.  * bits reliably, this will not do.  We should examine all of the fp classes.
  378.  */
  379.  
  380. #define _FP_NEG(fs, wc, R, X)        \
  381.   do {                    \
  382.     _FP_FRAC_COPY_##wc(R, X);        \
  383.     R##_c = X##_c;            \
  384.     R##_e = X##_e;            \
  385.     R##_s = 1 ^ X##_s;            \
  386.   } while (0)
  387.  
  388.  
  389. /*
  390.  * Main multiplication routine.  The input values should be cooked.
  391.  */
  392.  
  393. #define _FP_MUL(fs, wc, R, X, Y)            \
  394. do {                            \
  395.   R##_s = X##_s ^ Y##_s;                \
  396.   switch (_FP_CLS_COMBINE(X##_c, Y##_c))        \
  397.   {                            \
  398.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
  399.     R##_c = FP_CLS_NORMAL;                \
  400.     R##_e = X##_e + Y##_e + 1;                \
  401.                             \
  402.     _FP_MUL_MEAT_##fs(R,X,Y);                \
  403.                             \
  404.     if (_FP_FRAC_OVERP_##wc(fs, R))            \
  405.       _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);    \
  406.     else                        \
  407.       R##_e--;                        \
  408.     break;                        \
  409.                             \
  410.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):        \
  411.     _FP_CHOOSENAN(fs, wc, R, X, Y, '*');        \
  412.     break;                        \
  413.                             \
  414.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):    \
  415.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):        \
  416.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):        \
  417.     R##_s = X##_s;                    \
  418.                             \
  419.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):        \
  420.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):    \
  421.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):    \
  422.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):    \
  423.     _FP_FRAC_COPY_##wc(R, X);                \
  424.     R##_c = X##_c;                    \
  425.     break;                        \
  426.                             \
  427.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):    \
  428.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):        \
  429.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):        \
  430.     R##_s = Y##_s;                    \
  431.                             \
  432.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):    \
  433.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):    \
  434.     _FP_FRAC_COPY_##wc(R, Y);                \
  435.     R##_c = Y##_c;                    \
  436.     break;                        \
  437.                             \
  438.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):        \
  439.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):        \
  440.     R##_s = _FP_NANSIGN_##fs;                \
  441.     R##_c = FP_CLS_NAN;                    \
  442.     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);        \
  443.     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
  444.     break;                        \
  445.                             \
  446.   default:                        \
  447.     abort();                        \
  448.   }                            \
  449. } while (0)
  450.  
  451.  
  452. /*
  453.  * Main division routine.  The input values should be cooked.
  454.  */
  455.  
  456. #define _FP_DIV(fs, wc, R, X, Y)            \
  457. do {                            \
  458.   R##_s = X##_s ^ Y##_s;                \
  459.   switch (_FP_CLS_COMBINE(X##_c, Y##_c))        \
  460.   {                            \
  461.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
  462.     R##_c = FP_CLS_NORMAL;                \
  463.     R##_e = X##_e - Y##_e;                \
  464.                             \
  465.     _FP_DIV_MEAT_##fs(R,X,Y);                \
  466.     break;                        \
  467.                             \
  468.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):        \
  469.     _FP_CHOOSENAN(fs, wc, R, X, Y, '/');        \
  470.     break;                        \
  471.                             \
  472.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):    \
  473.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):        \
  474.   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):        \
  475.     R##_s = X##_s;                    \
  476.     _FP_FRAC_COPY_##wc(R, X);                \
  477.     R##_c = X##_c;                    \
  478.     break;                        \
  479.                             \
  480.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):    \
  481.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):        \
  482.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):        \
  483.     R##_s = Y##_s;                    \
  484.     _FP_FRAC_COPY_##wc(R, Y);                \
  485.     R##_c = Y##_c;                    \
  486.     break;                        \
  487.                             \
  488.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):    \
  489.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):        \
  490.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):    \
  491.     R##_c = FP_CLS_ZERO;                \
  492.     break;                        \
  493.                             \
  494.   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):    \
  495.     FP_SET_EXCEPTION(FP_EX_DIVZERO);            \
  496.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):        \
  497.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):    \
  498.     R##_c = FP_CLS_INF;                    \
  499.     break;                        \
  500.                             \
  501.   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):        \
  502.     R##_s = _FP_NANSIGN_##fs;                \
  503.     R##_c = FP_CLS_NAN;                    \
  504.     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);        \
  505.     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
  506.     break;                        \
  507.                             \
  508.   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):    \
  509.     R##_s = _FP_NANSIGN_##fs;                \
  510.     R##_c = FP_CLS_NAN;                    \
  511.     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);        \
  512.     FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
  513.     break;                        \
  514.                             \
  515.   default:                        \
  516.     abort();                        \
  517.   }                            \
  518. } while (0)
  519.  
  520.  
  521. /*
  522.  * Main differential comparison routine.  The inputs should be raw not
  523.  * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
  524.  */
  525.  
  526. #define _FP_CMP(fs, wc, ret, X, Y, un)                    \
  527.   do {                                    \
  528.     /* NANs are unordered */                        \
  529.     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))        \
  530.     || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))    \
  531.       {                                    \
  532.     ret = un;                            \
  533.       }                                    \
  534.     else                                \
  535.       {                                    \
  536.     int __is_zero_x;                        \
  537.     int __is_zero_y;                        \
  538.                                     \
  539.     __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;    \
  540.     __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;    \
  541.                                     \
  542.     if (__is_zero_x && __is_zero_y)                    \
  543.         ret = 0;                        \
  544.     else if (__is_zero_x)                        \
  545.         ret = Y##_s ? 1 : -1;                    \
  546.     else if (__is_zero_y)                        \
  547.         ret = X##_s ? -1 : 1;                    \
  548.     else if (X##_s != Y##_s)                    \
  549.       ret = X##_s ? -1 : 1;                        \
  550.     else if (X##_e > Y##_e)                        \
  551.       ret = X##_s ? -1 : 1;                        \
  552.     else if (X##_e < Y##_e)                        \
  553.       ret = X##_s ? 1 : -1;                        \
  554.     else if (_FP_FRAC_GT_##wc(X, Y))                \
  555.       ret = X##_s ? -1 : 1;                        \
  556.     else if (_FP_FRAC_GT_##wc(Y, X))                \
  557.       ret = X##_s ? 1 : -1;                        \
  558.     else                                \
  559.       ret = 0;                            \
  560.       }                                    \
  561.   } while (0)
  562.  
  563.  
  564. /* Simplification for strict equality.  */
  565.  
  566. #define _FP_CMP_EQ(fs, wc, ret, X, Y)                      \
  567.   do {                                      \
  568.     /* NANs are unordered */                          \
  569.     if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))          \
  570.     || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))      \
  571.       {                                      \
  572.     ret = 1;                              \
  573.       }                                      \
  574.     else                                  \
  575.       {                                      \
  576.     ret = !(X##_e == Y##_e                          \
  577.         && _FP_FRAC_EQ_##wc(X, Y)                  \
  578.         && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
  579.       }                                      \
  580.   } while (0)
  581.  
  582. /*
  583.  * Main square root routine.  The input value should be cooked.
  584.  */
  585.  
  586. #define _FP_SQRT(fs, wc, R, X)                        \
  587. do {                                    \
  588.     _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);            \
  589.     _FP_W_TYPE q;                            \
  590.     switch (X##_c)                            \
  591.     {                                    \
  592.     case FP_CLS_NAN:                            \
  593.     _FP_FRAC_COPY_##wc(R, X);                    \
  594.     R##_s = X##_s;                            \
  595.         R##_c = FP_CLS_NAN;                        \
  596.         break;                                \
  597.     case FP_CLS_INF:                            \
  598.         if (X##_s)                            \
  599.           {                                \
  600.             R##_s = _FP_NANSIGN_##fs;                    \
  601.         R##_c = FP_CLS_NAN; /* NAN */                \
  602.         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
  603.         FP_SET_EXCEPTION(FP_EX_INVALID);                \
  604.           }                                \
  605.         else                                \
  606.           {                                \
  607.             R##_s = 0;                            \
  608.             R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */            \
  609.           }                                \
  610.         break;                                \
  611.     case FP_CLS_ZERO:                            \
  612.     R##_s = X##_s;                            \
  613.     R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */            \
  614.     break;                                \
  615.     case FP_CLS_NORMAL:                            \
  616.         R##_s = 0;                            \
  617.         if (X##_s)                            \
  618.           {                                \
  619.         R##_c = FP_CLS_NAN; /* sNAN */                \
  620.         R##_s = _FP_NANSIGN_##fs;                    \
  621.         _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
  622.         FP_SET_EXCEPTION(FP_EX_INVALID);                \
  623.         break;                            \
  624.           }                                \
  625.         R##_c = FP_CLS_NORMAL;                        \
  626.         if (X##_e & 1)                            \
  627.           _FP_FRAC_SLL_##wc(X, 1);                    \
  628.         R##_e = X##_e >> 1;                        \
  629.         _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);            \
  630.         _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);            \
  631.         q = _FP_OVERFLOW_##fs >> 1;                    \
  632.         _FP_SQRT_MEAT_##wc(R, S, T, X, q);                \
  633.     }                                    \
  634.   } while (0)
  635.  
  636. /*
  637.  * Convert from FP to integer
  638.  */
  639.  
  640. /* RSIGNED can have following values:
  641.  * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
  642.  *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
  643.  * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  644.  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  645.  *     on the sign in such case.
  646.  * 2:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
  647.  *     set plus the result is truncated to fit into destination.
  648.  * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
  649.  *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
  650.  *     on the sign in such case.
  651.  */
  652. #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                \
  653.   do {                                        \
  654.     switch (X##_c)                                \
  655.       {                                        \
  656.       case FP_CLS_NORMAL:                            \
  657.     if (X##_e < 0)                                \
  658.       {                                    \
  659.         FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
  660.       case FP_CLS_ZERO:                            \
  661.         r = 0;                                \
  662.       }                                    \
  663.     else if (X##_e >= rsize - (rsigned > 0 || X##_s)            \
  664.          || (!rsigned && X##_s))                    \
  665.       {    /* overflow */                            \
  666.       case FP_CLS_NAN:                                                      \
  667.       case FP_CLS_INF:                            \
  668.         if (rsigned == 2)                            \
  669.           {                                    \
  670.         if (X##_c != FP_CLS_NORMAL                    \
  671.             || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)            \
  672.           r = 0;                            \
  673.         else                                \
  674.           {                                \
  675.             _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));    \
  676.             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
  677.           }                                \
  678.           }                                    \
  679.         else if (rsigned)                            \
  680.           {                                    \
  681.         r = 1;                                \
  682.         r <<= rsize - 1;                        \
  683.         r -= 1 - X##_s;                            \
  684.           }                                    \
  685.         else                                \
  686.           {                                    \
  687.         r = 0;                                \
  688.         if (X##_s)                            \
  689.           r = ~r;                            \
  690.           }                                    \
  691.         FP_SET_EXCEPTION(FP_EX_INVALID);                    \
  692.       }                                    \
  693.     else                                    \
  694.       {                                    \
  695.         if (_FP_W_TYPE_SIZE*wc < rsize)                    \
  696.           {                                    \
  697.         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
  698.         r <<= X##_e - _FP_WFRACBITS_##fs;                \
  699.           }                                    \
  700.         else                                \
  701.           {                                    \
  702.         if (X##_e >= _FP_WFRACBITS_##fs)                \
  703.           _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));    \
  704.         else if (X##_e < _FP_WFRACBITS_##fs - 1)            \
  705.           {                                \
  706.             _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),    \
  707.                       _FP_WFRACBITS_##fs);            \
  708.             if (_FP_FRAC_LOW_##wc(X) & 1)                \
  709.               FP_SET_EXCEPTION(FP_EX_INEXACT);                \
  710.             _FP_FRAC_SRL_##wc(X, 1);                    \
  711.           }                                \
  712.         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
  713.           }                                    \
  714.         if (rsigned && X##_s)                        \
  715.           r = -r;                                \
  716.       }                                    \
  717.     break;                                    \
  718.       }                                        \
  719.   } while (0)
  720.  
  721. #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)                \
  722.   do {                                        \
  723.     r = 0;                                    \
  724.     switch (X##_c)                                \
  725.       {                                        \
  726.       case FP_CLS_NORMAL:                            \
  727.     if (X##_e >= _FP_FRACBITS_##fs - 1)                    \
  728.       {                                    \
  729.         if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)                \
  730.           {                                    \
  731.         if (X##_e >= _FP_WFRACBITS_##fs - 1)                \
  732.           {                                \
  733.             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
  734.             r <<= X##_e - _FP_WFRACBITS_##fs + 1;            \
  735.           }                                \
  736.         else                                \
  737.           {                                \
  738.             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e            \
  739.                       + _FP_FRACBITS_##fs - 1);            \
  740.             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);            \
  741.           }                                \
  742.           }                                    \
  743.       }                                    \
  744.     else                                    \
  745.       {                                    \
  746.         if (X##_e <= -_FP_WORKBITS - 1)                    \
  747.           _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                \
  748.         else                                \
  749.           _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,        \
  750.                 _FP_WFRACBITS_##fs);                \
  751.         _FP_ROUND(wc, X);                            \
  752.         _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                    \
  753.         _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                \
  754.       }                                    \
  755.     if (rsigned && X##_s)                            \
  756.       r = -r;                                \
  757.     if (X##_e >= rsize - (rsigned > 0 || X##_s)                \
  758.         || (!rsigned && X##_s))                        \
  759.       {    /* overflow */                            \
  760.       case FP_CLS_NAN:                                                      \
  761.       case FP_CLS_INF:                            \
  762.         if (!rsigned)                            \
  763.           {                                    \
  764.         r = 0;                                \
  765.         if (X##_s)                            \
  766.           r = ~r;                            \
  767.           }                                    \
  768.         else if (rsigned != 2)                        \
  769.           {                                    \
  770.         r = 1;                                \
  771.         r <<= rsize - 1;                        \
  772.         r -= 1 - X##_s;                            \
  773.           }                                    \
  774.         FP_SET_EXCEPTION(FP_EX_INVALID);                    \
  775.       }                                    \
  776.     break;                                    \
  777.       case FP_CLS_ZERO:                                \
  778.         break;                                    \
  779.       }                                        \
  780.   } while (0)
  781.  
  782. #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)            \
  783.   do {                                    \
  784.     if (r)                                \
  785.       {                                    \
  786.         unsigned rtype ur_;                        \
  787.     X##_c = FP_CLS_NORMAL;                        \
  788.                                     \
  789.     if ((X##_s = (r < 0)))                        \
  790.       ur_ = (unsigned rtype) -r;                    \
  791.     else                                \
  792.       ur_ = (unsigned rtype) r;                    \
  793.     if (rsize <= _FP_W_TYPE_SIZE)                    \
  794.       __FP_CLZ(X##_e, ur_);                        \
  795.     else                                \
  796.       __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),     \
  797.              (_FP_W_TYPE)ur_);                    \
  798.     if (rsize < _FP_W_TYPE_SIZE)                    \
  799.         X##_e -= (_FP_W_TYPE_SIZE - rsize);            \
  800.     X##_e = rsize - X##_e - 1;                    \
  801.                                     \
  802.     if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)    \
  803.       __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
  804.     _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);            \
  805.     if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)            \
  806.       _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));    \
  807.       }                                    \
  808.     else                                \
  809.       {                                    \
  810.     X##_c = FP_CLS_ZERO, X##_s = 0;                    \
  811.       }                                    \
  812.   } while (0)
  813.  
  814.  
  815. #define FP_CONV(dfs,sfs,dwc,swc,D,S)            \
  816.   do {                            \
  817.     _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);    \
  818.     D##_e = S##_e;                    \
  819.     D##_c = S##_c;                    \
  820.     D##_s = S##_s;                    \
  821.   } while (0)
  822.  
  823. /*
  824.  * Helper primitives.
  825.  */
  826.  
  827. /* Count leading zeros in a word.  */
  828.  
  829. #ifndef __FP_CLZ
  830. #if _FP_W_TYPE_SIZE < 64
  831. /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
  832. #define __FP_CLZ(r, x)                \
  833.   do {                        \
  834.     _FP_W_TYPE _t = (x);            \
  835.     r = _FP_W_TYPE_SIZE - 1;            \
  836.     if (_t > 0xffff) r -= 16;            \
  837.     if (_t > 0xffff) _t >>= 16;            \
  838.     if (_t > 0xff) r -= 8;            \
  839.     if (_t > 0xff) _t >>= 8;            \
  840.     if (_t & 0xf0) r -= 4;            \
  841.     if (_t & 0xf0) _t >>= 4;            \
  842.     if (_t & 0xc) r -= 2;            \
  843.     if (_t & 0xc) _t >>= 2;            \
  844.     if (_t & 0x2) r -= 1;            \
  845.   } while (0)
  846. #else /* not _FP_W_TYPE_SIZE < 64 */
  847. #define __FP_CLZ(r, x)                \
  848.   do {                        \
  849.     _FP_W_TYPE _t = (x);            \
  850.     r = _FP_W_TYPE_SIZE - 1;            \
  851.     if (_t > 0xffffffff) r -= 32;        \
  852.     if (_t > 0xffffffff) _t >>= 32;        \
  853.     if (_t > 0xffff) r -= 16;            \
  854.     if (_t > 0xffff) _t >>= 16;            \
  855.     if (_t > 0xff) r -= 8;            \
  856.     if (_t > 0xff) _t >>= 8;            \
  857.     if (_t & 0xf0) r -= 4;            \
  858.     if (_t & 0xf0) _t >>= 4;            \
  859.     if (_t & 0xc) r -= 2;            \
  860.     if (_t & 0xc) _t >>= 2;            \
  861.     if (_t & 0x2) r -= 1;            \
  862.   } while (0)
  863. #endif /* not _FP_W_TYPE_SIZE < 64 */
  864. #endif /* ndef __FP_CLZ */
  865.  
  866. #define _FP_DIV_HELP_imm(q, r, n, d)        \
  867.   do {                        \
  868.     q = n / d, r = n % d;            \
  869.   } while (0)
  870.  
  871. #endif /* __MATH_EMU_OP_COMMON_H__ */
  872.